package pers.mihao.quickstream.common.plus.log.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import pers.mihao.quickstream.common.plus.log.model.AbstractLog;
import pers.mihao.quickstream.common.plus.log.annotation.PersistentLog;
import pers.mihao.quickstream.common.util.DateUtil;
import pers.mihao.quickstream.common.util.ReflectionUtil;
import pers.mihao.quickstream.common.util.StringUtil;
import pers.mihao.quickstream.common.util.biz.CurrUserIdHolder;

import java.lang.reflect.Method;

/**
 * 写日志的拦截器
 *
 * @author mihao
 */
@Aspect
@Slf4j
public class PersistentLogAspect {

    @Pointcut("@annotation(pers.mihao.quickstream.common.plus.log.annotation.PersistentLog))")
    public void PersistentLog() {
    }

    @Around("PersistentLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Method proxyMethod = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Method targetMethod = joinPoint.getTarget().getClass().getMethod(proxyMethod.getName(),
                proxyMethod.getParameterTypes());

        PersistentLog persistentLog = targetMethod.getAnnotation(PersistentLog.class);
        if (persistentLog != null) {
            long start = System.currentTimeMillis();
            // 执行方法
            Object res = joinPoint.proceed();
            long end = System.currentTimeMillis();
            try {
                doRecordLog(joinPoint, persistentLog, end, start, proxyMethod, res);
            } catch (Exception e) {
                log.error("recordLog error");
            }
            return res;
        } else {
            return joinPoint.proceed();
        }
    }

    private void doRecordLog(ProceedingJoinPoint joinPoint, PersistentLog persistentLog,
                             long end, long start, Method method, Object res) throws IllegalAccessException, InstantiationException {
        AbstractLog log = ReflectionUtil.getNewInstance(persistentLog.bean());
        if (StringUtil.isNotBlack(persistentLog.tableName())) {
            log.setTableName(persistentLog.tableName());
        }
        if (StringUtil.isNotBlack(persistentLog.dataSource())) {
            log.setDataSource(persistentLog.dataSource());
        }
        log.setAsync(persistentLog.isAsync());
        log.setUnderscore(persistentLog.isUnderscore());
        log.setCreateTime(DateUtil.getDataTime());
        log.setExecTime(end - start);
        log.setInvokeMethod(method.getName());
        log.setServiceName(joinPoint.getThis().toString());
        log.setTriggerUserId(CurrUserIdHolder.getUserId());
        log.setArgs(joinPoint.getArgs());
        log.setRes(res);
        ReflectionUtil.getSingleton(log.getInvoke()).doPersistLog(log);
    }
}